package com.apobates.forum.toro.tuple;

import com.apobates.forum.toro.tuple.strategy.PairSupplyFutureStrategy;
import com.apobates.forum.toro.tuple.strategy.PairSupplyStrategy;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 左对象是单实例的Pair映射执行器
 * 左对象与右对象一对一模式的执行器
 * @param <L> 左对象类型
 * @since 20220827
 * @author xiaofanku@live.cn
 */
public class PairMapperExecutor<L> {
    private final Supplier<L> leftObjFun;
    private final Map<String,String> arguments;
    private static final Logger logger = LoggerFactory.getLogger(PairMapperExecutor.class);

    public PairMapperExecutor(Supplier<L> leftObjFun, Map<String, String> arguments) {
        this.leftObjFun = leftObjFun;
        this.arguments = arguments;
    }

    /**
     *
     * @param consumer
     * @return
     * @param <R>
     */
    public <R> Builder<R,Pair<L, R>> consume(Consumer<Pair<L,R>> consumer){
        PairResultMapperTransfer<L,R,Pair<L, R>> transfer = new PairResultMapperTransfer<>(){
            @Override
            public Consumer<Pair<L, R>> getConsumer() {
                return consumer;
            }
            @Override
            public Function<Pair<L, R>, Pair<L, R>> getFormater() {
                return Function.identity();
            }
        };
        return new Builder<>(transfer);
    }

    /**
     *
     * @param formater
     * @return
     * @param <R>
     * @param <F>
     */
    public <R,F> Builder<R,F> format(Function<Pair<L,R>,F> formater){
        PairResultMapperTransfer<L,R,F> transfer = new PairResultMapperTransfer<>(){
            @Override
            public Consumer<Pair<L, R>> getConsumer() {
                return (Pair<L, R> ins)->logger.info("PairMapperExecutor Default Consumer");
            }
            @Override
            public Function<Pair<L, R>, F> getFormater() {
                return formater;
            }
        };
        return new Builder<>(transfer);
    }

    /**
     *
     * @param transfer
     * @return
     * @param <R>
     * @param <F>
     */
    public <R,F> Builder<R,F> transfer(PairResultMapperTransfer<L,R,F> transfer){
        return new Builder<>(transfer);
    }

    public Supplier<L> getLeftObjFun() {
        return leftObjFun;
    }
    public Map<String, String> getArguments() {
        return arguments;
    }

    /**
     * 使用内置的PairSupplyFutureStrategy异步策略返回执行结果
     * @param rightFun 右对象查询函数
     * @return
     * @param <R> 右对象的类型
     * @param <U> 右函数的参数类型
     */
    public <R,U> Pair<L,R> get(Function<U, R> rightFun) {
        return this.get(rightFun, new PairSupplyFutureStrategy<>());
    }

    /**
     * 使用指定聚合策略返回执行结果
     * @param rightFun 右对象查询函数
     * @param strategy 聚合策略
     * @return
     * @param <R> 右对象的类型
     * @param <U> 右函数的参数类型
     */
    public <R,U> Pair<L,R> get(Function<U, R> rightFun, PairSupplyStrategy<L,R,U> strategy) {
        return strategy.apply(getLeftObjFun(), rightFun, getArguments());
    }

    public class Builder<R,F>{
        private final PairResultMapperTransfer<L,R,F> transfer;

        private Builder(PairResultMapperTransfer<L,R,F> transfer){
            this.transfer = transfer;
        }

        /**
         *
         * @param rightFun
         * @return
         * @param <U>
         */
        public <U> F get(Function<U, R> rightFun){
            Pair<L, R> pair = PairMapperExecutor.this.get(rightFun);
            return this.transfer.get(pair);
        }

        /**
         *
         * @param rightFun
         * @param strategy
         * @return
         * @param <U>
         */
        public <U> F get(Function<U, R> rightFun, PairSupplyStrategy<L,R,U> strategy){
            Pair<L, R> pair = PairMapperExecutor.this.get(rightFun, strategy);
            return this.transfer.get(pair);
        }
    }
}
